package com.java.JDBCView;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class JDBCUtils {
    // 数据库连接信息
    public static final String URL1 = "jdbc:mysql://localhost:3306/aigou?serverTimezone=GMT&useUnicode=true&characterEncoding=UTF-8&useSSL=false";
    public static final String USERNAME1 = "root";
    public static final String PASSWORD1 = "root";

    /**
     * 执行增删改操作
     * @param sql SQL语句
     * @param params 可变参数，SQL语句参数的值
     * @return 影响的行数
     */
    public static int executeUpdate(String sql, Object... params) {
        // 加载驱动
        try (Connection connection = DriverManager.getConnection(URL1, USERNAME1, PASSWORD1);
             // 创建SQL语句执行对象
             PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
            // 为SQL语句设置参数,索引从1开始
            for (int i = 0; i < params.length; i++) {
                //索引从1开始,参数从0开始
                preparedStatement.setObject(i + 1, params[i]);
            }
            // 执行SQL语句，返回preparedStatement对象的一个方法，并不是递归
            return preparedStatement.executeUpdate();
        } catch (SQLException ex) {
            // 打印异常信息
            ex.printStackTrace();
            // 抛出运行时异常
            throw new RuntimeException("数据库操作失败: " + ex.getMessage(), ex);
        }
    }

    /**
     * 执行查询操作
     * @param clazz 返回的结果集类型
     * @param sql SQL语句
     * @param params 占位符参数
     * @return 泛型集合
     * @param <T> 泛型类型
     */
    public static <T> List<T> executeQuery(Class<T> clazz, String sql, Object... params) {
        // 加载驱动
        try (Connection connection = DriverManager.getConnection(URL1, USERNAME1, PASSWORD1);
             // 创建SQL语句执行对象
             PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
            //为SQL语句设置参数,索引从1开始
            for (int i = 0; i < params.length; i++) {
                //索引从1开始,参数从0开始
                preparedStatement.setObject(i + 1, params[i]);
            }

            // 执行SQL语句,返回preparedStatement对象的一个方法
            ResultSet rs = preparedStatement.executeQuery();
            // 声明一个名为 list 的变量，其类型为 List<T>。
            //将新创建的 ArrayList 实例赋值给 list 变量。
            List<T> list = new ArrayList<>();

            // 遍历结果集
            while (rs.next()) {
                // 创建一个 clazz 类的新实例，并将其赋值给 object 变量。
                //getDeclaredConstructor() 方法返回一个 Constructor 对象，表示该类的默认构造函数（无参构造函数）。
                //newInstance() 方法调用该构造函数，创建并返回一个新的实例。
                T object = clazz.getDeclaredConstructor().newInstance();
                //clazz.getDeclaredFields();：
                //getDeclaredFields() 方法返回一个 Field 数组，表示 clazz 类中声明的所有字段（包括私有字段）。
                //作用：获取 clazz 类中所有字段的数组，并将其赋值给 fields 变量。
                Field[] fields = clazz.getDeclaredFields();

                for (Field field : fields) {
                    //当设置为 true 时，即使字段是私有的（private），也可以通过反射机制访问和修改该字段的值。
                    field.setAccessible(true);
                    //getObject(field.getName()) 方法从 ResultSet 中获取与字段名称对应的值。
                    field.set(object, rs.getObject(field.getName()));
                }

                //将创建并填充好的 object 对象添加到 list 列表中
                list.add(object);
            }

            // 返回 list 列表
            return list;
        }
        //catch 块用于捕获在 try 块中抛出的异常。
        //Exception 是所有异常的基类，捕获 Exception 可以捕获所有类型的异常。
        //e 是捕获到的异常对象，表示具体的异常信息
        catch (Exception e) {
            //打印异常信息
            e.printStackTrace();
            // 作为 RuntimeException 的原因传递，保留了原始异常的完整信息
            throw new RuntimeException("数据库查询失败: " + e.getMessage(), e);
        }
    }
}
